package com.eras.shoes.utils;

import android.util.Log;
import android.util.Pair;

import com.eras.shoes.contents.BleDataEx;
import com.eras.shoes.contents.BulDataObject;
import com.eras.shoes.contents.CalibrateBean;
import com.eras.shoes.contents.Global;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Queue;

public class DataComputingManage {
    public final static double  hPa_default_value= 1;
//    public final static double  hPa_default_value= 0.000934777;
//    public final static double  default_value= 8.8889;//
//    public final static double  default_value= 4.4444;
    public final static double  default_value= 0;
//    public static double weight_coefficient = 1.2147097;
//    public static Queue<BulDataObject> lDateQueue = new ArrayDeque<>();
    public static Queue<BulDataObject> DateQueue = new ArrayDeque<>();
    public final static int dateQueueSize = 11;
    public static Integer lWeight = 0; //左负重值
    public static Long lTimestamp = 0L; //左负重值时间戳
    public static Integer rWeight = 0; //右负重值
    public static Long rTimestamp = 0L; //右负重值时间戳
    public static Integer totalWeight = 0; //右负重值
    public final static Integer timeInterval = 60; //右负重值

    public static List<Integer> sum = Arrays.asList(0, 20, 50, 70, 100);
    public static List<Float> pressCal = new ArrayList<>();
    public static float Fsure = 0;

//    public static void initRestore(){
//        lWeight = 0;
//        lTimestamp = 0L;
//        rWeight = 0;
//
//        rTimestamp = 0L;
//        totalWeight = 0;
//        lDateQueue.clear();
//        rDateQueue.clear();
//    }
    /**
     * 评估/训练页面负重、热力图计算
     * @param data
     * @return
     */
    public static Float getComputingResult(DataComputingObject data, List<CalibrateBean.press> press){
        //Log.i("计算 - ",JSONObject.toJSONString(data));
//        DateQueue.clear();
        //蓝牙数据进行业务逻辑解析
        BulDataObject bulDataObject = dateInversion(data);
        BleDataEx.BleData bulDate = data.getBulDate();
        Double pressureData;
        pressureData = getPressureEvaluationValue();//平均压力
        pressCal.clear();
        if (press.isEmpty()) {
            return 0f;
        }
        for (CalibrateBean.press p: press) {
            pressCal.add(Float.valueOf(p.getDifference()));
        }

        double pa = subtract((double)pressureData, Global.P0);

        Float[] result = findNumberRange((float) pa, pressCal);
        System.out.println(pressureData + " 位于 " + result[0] + " 和 " + result[1] + " 之间");
        Log.e("CalibrateActivity", "实时压力="+pressureData + " 位于 " + result[0] + " 和 " + result[1] + " 之间");
        String pressure0 = "0";
        String pressure1 = "0";
        for (CalibrateBean.press p: press) {
           if (Float.valueOf(p.getDifference()).equals(result[0])){
               pressure0 = p.getPressure();
           }
            if (Float.valueOf(p.getDifference()).equals(result[1])){
                pressure1 = p.getPressure();
            }
        }

        double F0 = Double.valueOf(pressure0);
        double F1 = Double.valueOf(pressure1);

        if (F0 == 0 && F1 == 0) {
            Fsure = 0;
        }
//        else if (F0 == 0 && F1 == 20) {
//            Fsure = (float) countZT(result[1], result[0], pa);
//        } else if (F0 == 20 && F1 == 50) {
//            Fsure = (float) countTF(result[1], result[0], pa);
//        } else if (F0 == 50 && F1 == 70) {
//            Fsure = (float) countFS(result[1], result[0], pa);
//        } else if (F0 == 70 && F1 == 100) {
//            Fsure =(float) countST(result[1], result[0], pa);
//        }
//        else
//            if (F0 == 100 && F1 == 100) {
//            Fsure = (float) countST(result[1], result[0], pa);
//        }

        double FF = subtract(F1, F0);
        double PP = subtract((double)result[1], (double)result[0]);
        double Pi = subtract(pa, (double)result[0]);

        if (PP != 0) {
            Fsure = (float) count(FF, PP, Pi, F0);
        }

        if (F0 >= 100) {
            F0 = 70;
            F1 = 100;
            double diffP0 = 0;
            double diffP1 = 0;
            for (CalibrateBean.press p: press) {
                if (p.getPressure().equals("70")){
                    diffP0 = Double.parseDouble(p.getDifference());
                }
                if (p.getPressure().equals("100")){
                    diffP1 = Double.parseDouble(p.getDifference());
                }
            }
            FF = subtract(F1, F0);
            PP = subtract(diffP1, diffP0);
            Pi = subtract(pa, diffP0);
            if (PP != 0) {
                Fsure = (float) count(FF, PP, Pi, F0);
            }


        }

        return Fsure;











        //获取清零结果
//        CalibrationObject calibrationObject = data.getCalibrationObject();
////        List<List<Map<String, Object>>> list;
//        JSONArray list;
//
//        Integer weight = null;
//        Double value;
//        int size = 0 ;
//        if (data.getLeftOrRightSigns() == 1){
//            value = getPressureEvaluationValue(data.getLeftOrRightSigns());
////            weight = (int) (getPress(calibrationDataObject.area,calibrationObject.lResetValue,value));//计算单脚踩踏重量
//            weight = (int) (getPress(ShoesAreaUtils.getShoesLeftArea(),calibrationObject.lResetValue,value));//计算单脚踩踏重量
////            list = calibrationDataObject.lLisr;
//            list = ShoesPressUtils.getlList();
//            lWeight = weight;//更新负重
//            lTimestamp = data.getBulDate().timestamp;//更新负重值时间戳
//            size = lDateQueue.size();
//        }else {
//            value = getPressureEvaluationValue(data.getLeftOrRightSigns());
////            weight = (int) (getPress(calibrationDataObject.area,calibrationObject.rResetValue,value));
//            weight = (int) (getPress(ShoesAreaUtils.getShoesRightArea(),calibrationObject.rResetValue,value));
////            list = calibrationDataObject.rLisr;
//            list = ShoesPressUtils.getrList();
//            rWeight = weight;//更新负重
//            rTimestamp = data.getBulDate().timestamp;//更新负重值时间戳
//            size = rDateQueue.size();
//        }
////        long currTime=System.currentTimeMillis();
////        currTime-=data.bulDate.mRecvTimestamp;
////        Log.i("计算结果 ","weight="+weight+",value="+value +"      RecvTime:"+data.bulDate.mRecvTimestamp +"  duration:"+currTime+"     devTime:"+data.bulDate.timestamp);
//        SmartShoesBean leftBean = null;
//        SmartShoesBean rightBean = null;
//        //获取总负重
////        Integer totalWeight = null;
//        // 取出左右脚数据
//        List<SmartShoesBean> smartShoes = SmartShoesSPUtils.getSmartShoesSPUtils().getSmartShoesKey(String.valueOf(SPHelper.getUserId()));
//        for (SmartShoesBean smartShoe : smartShoes) {
//            if (smartShoe.getType() == 1) {
//                //左脚
//                leftBean = smartShoe;
//            } else if (smartShoe.getType() == 2) {
//                // 右脚
//                rightBean = smartShoe;
//            }
//        }
//        if (leftBean == null && rightBean != null) {//仅右脚
////            totalWeight = Integer.valueOf(SPHelper.getUser().getWeight());
//            totalWeight = lWeight + rWeight;
//        } else if (leftBean != null && rightBean == null) {//仅左脚
////            totalWeight = Integer.valueOf(SPHelper.getUser().getWeight());
//            totalWeight = lWeight + rWeight;
//        }  else if (leftBean != null && rightBean != null) {//双脚
//            getTotalWeight(data.getLeftOrRightSigns());
//        }
//
//        Log.i("getComputingResult ","totalWeight:"+totalWeight+" type："+data.getLeftOrRightSigns()+" 负重："+weight+" 平均压力："+value +" 压力:"+bulDataObject.getPressureData()+" 队列长度："+size);
//        Log.e("getComputingResult", "getComputingResult_List="+list);
//        List<Float> bulEvaluationValue = getBulEvaluationValue(data.getLeftOrRightSigns());//获取过滤后10个点的平均值
//        List<Long> pressureWeight = computingPressure(bulEvaluationValue, list);//将平均值转换为重量
//        List<Float> pressureRatioList = computingPressureRatio(pressureWeight,weight);//通过重量计算压力占比
//        return new ComputingResult(
//                weight,
//                totalWeight,
//                pressureRatioList,
//                bulDataObject.getQuantityElectricity(),
//                bulDataObject.getBluSignal(),
//                pressureWeight,
//                BigDecimal.valueOf(bulDataObject.getTemperature()).setScale(0, RoundingMode.HALF_UP).intValue(),
//                data.getBulDate().timestamp
//        );
//        return pressureData;
    }

    public static Float[] findNumberRange(float target, List<Float> rangeLists) {
        // 创建列表的副本进行操作，避免并发修改造成异常
        List<Float> rangeList = new ArrayList<>(rangeLists);
        // 确保列表是有序的
        Collections.sort(rangeList);

        // 如果目标小于最小值，返回前两个数
        if (target <= rangeList.get(0)) {
            return new Float[]{rangeList.get(0), rangeList.get(1)};
        }

        // 如果目标大于最大值，返回最后两个数
        if (target >= rangeList.get(rangeList.size() - 1)) {
            return new Float[]{rangeList.get(rangeList.size() - 2),
                    rangeList.get(rangeList.size() - 1)};
        }

        // 遍历查找区间
        for (int i = 0; i < rangeList.size() - 1; i++) {
            if (target >= rangeList.get(i) && target <= rangeList.get(i + 1)) {
                return new Float[]{rangeList.get(i), rangeList.get(i + 1)};
            }
        }

        // 默认返回第一个区间（理论上不会执行到这里）
        return new Float[]{rangeList.get(0), rangeList.get(1)};
    }

    // 加法
    public static double add(double a, double b) {
        return a + b;
    }

    // 减法
    public static double subtract(double a, double b) {
        return a - b;
    }

    // 乘法
    public static double multiply(double a, double b) {
        return a * b;
    }

    // 除法
    public static double divide(double a, double b) {
        if (b == 0) {
            throw new ArithmeticException("除数不能为零");
        }
        return a / b;
    }

    public static double count(double FF, double PP, double Pi, double F0) {
        double F = 0;
        double FP = divide(FF, PP);//除法
        double FPPi = multiply(FP, Pi);//乘法
        F = add(FPPi, F0);

        return F;
    }

    //0到20
    public static double countZT(double result0, double result1, double pa) {
        double F = 0;
        double FF = subtract(20, 0);
        double PP = subtract(result1, result0);
        double Pi = subtract(pa, result0);
        F = count(FF, PP, Pi, 0);
        return F;
    }
    //20到50
    public static double countTF(double result0, double result1, double pa) {
        double F = 0;
        double FF = subtract(50, 20);
        double PP = subtract(result1, result0);
        double Pi = subtract(pa, result0);
        F = count(FF, PP, Pi, 20);
        return F;
    }
    //50到70
    public static double countFS(double result0, double result1, double pa) {
        double F = 0;
        double FF = subtract(70, 50);
        double PP = subtract(result1, result0);
        double Pi = subtract(pa, result0);
        F = count(FF, PP, Pi, 50);
        return F;
    }
    //70到100
    public static double countST(double result0, double result1, double pa) {
        double F = 0;
        double FF = subtract(100, 70);
        double PP = subtract(result1, result0);
        double Pi = subtract(pa, result0);
        F = count(FF, PP, Pi, 70);
        return F;
    }


    /**
     *  蓝牙数据处理
     * @param data
     */
    private static BulDataObject dateInversion(DataComputingObject data){
        BleDataEx.BleData bulDate = data.getBulDate();
        List<Float> pressurePointData = bulDate.dataList.subList(0, 10);//10个压力点数据
        Log.e("DataComputingManage", "pressurePointData="+pressurePointData);
        int quantityElectricity = calculateElectricityConsumption(bulDate.dataList.get(22));//电量
        Float bluSignal = bulDate.dataList.get(24);//蓝牙信号
        Float tdmp = bulDate.dataList.get(27);//温度
        Float pressureData = bulDate.dataList.get(28);//压力
        BulDataObject bulDataObject = new BulDataObject(pressurePointData,quantityElectricity,bluSignal,tdmp,pressureData);
//        if (data.getLeftOrRightSigns() == 1){
//
//        }else {
//            if (rDateQueue.size() == dateQueueSize){
//                rDateQueue.poll();
//            }
//            rDateQueue.offer(bulDataObject);
//        }
        if (DateQueue.size() == dateQueueSize){
            DateQueue.poll();
        }
        DateQueue.offer(bulDataObject);
        return bulDataObject;
    }



    /**
     * 计算单脚踩踏重量
     * 公式：鞋垫面积 *（实时压力-校准压力）* hPa固定值 = 单脚踩踏重量
     * @param area 鞋垫面积
     * @param cPressure 校准压力
     * @param pressure 实时压力
     * @return
     */
//    private static Integer computingWeight(Double area,Double cPressure,Double pressure){
//        BigDecimal areaBigDecimal = new BigDecimal(area);
//        BigDecimal cPressureBigDecimal = new BigDecimal(cPressure);
//        BigDecimal pressureBigDecimal = new BigDecimal(pressure);
//        BigDecimal subtract = pressureBigDecimal.subtract(cPressureBigDecimal);
//        BigDecimal bigDecimal = areaBigDecimal.multiply(subtract).multiply(new BigDecimal(hPa_default_value))
//                .subtract(new BigDecimal(default_value))
//                .setScale(0, RoundingMode.DOWN);
//        int compareTo = bigDecimal.compareTo(new BigDecimal(0));
//        return  compareTo >= 0 ?Integer.parseInt(bigDecimal.toString()):0;
//    }
//
//    private static Double getWeight(Double area,Double cPressure,Double pressure) {
//        BigDecimal areaBigDecimal = new BigDecimal(area);
//        BigDecimal cPressureBigDecimal = new BigDecimal(cPressure);
//        BigDecimal pressureBigDecimal = new BigDecimal(pressure);
//        BigDecimal subtract = pressureBigDecimal.subtract(cPressureBigDecimal);
//        BigDecimal bigDecimal = areaBigDecimal.multiply(subtract).setScale(0, RoundingMode.DOWN);
//        int compareTo = bigDecimal.compareTo(new BigDecimal(0));
//        return compareTo >= 0 ? Double.parseDouble(bigDecimal.toString()) : 0;
//    }
//
//    private static Integer getPress(Double area,Double cPressure,Double pressure){
//        Double weight = getWeight(area, cPressure, pressure);
//        BigDecimal a = new BigDecimal(weight).multiply(new BigDecimal(weight)).multiply(new BigDecimal(Global.a));
//        BigDecimal b = new BigDecimal(weight).multiply(new BigDecimal(Global.b));
//        return a.add(b).add(new BigDecimal(Global.c)).intValue();
//    }

    /**
     * 10个点位的压力占比
     * @param pressureWeight 十个点负重数据
     * @param weight 单脚负重
     * @return
     */
    private static List<Float> computingPressureRatio(List<Long> pressureWeight, Integer weight){
        List<Float> ratioList = new ArrayList<>();
        if (pressureWeight == null || pressureWeight.size() == 0)return null;

        float sum = 0;//总压力
        for (long item : pressureWeight) {
            sum = sum + item;
        }

        for (int i = 0; i < pressureWeight.size(); i++) {
            float r = 0;
            if (sum > 0 && totalWeight > 0){
                r = BigDecimal.valueOf(pressureWeight.get(i) / sum * weight / totalWeight * 300)
                        .setScale(2, RoundingMode.HALF_UP)
                        .floatValue() ;
            }
            ratioList.add(r);
        }

        List<Long> integers = pressureWeight.subList(0, 6);
        int a1= 0;
        for (Long integer : integers) {
            a1+=integer;
        }
        Float val1 = sum == 0? (float) 0.0 :BigDecimal.valueOf(Float.parseFloat(String.valueOf(a1)) / sum * 100).setScale(2, RoundingMode.HALF_UP).floatValue();
        ratioList.add(val1);

        List<Long> integers1 = pressureWeight.subList(6, 10);
        int a2= 0;
        for (Long integer : integers1) {
            a2+=integer;
        }
        Float val2 = sum == 0? (float) 0.0 :BigDecimal.valueOf(Float.parseFloat(String.valueOf(a2)) / sum * 100).setScale(2, RoundingMode.HALF_UP).floatValue();
        ratioList.add(val2);
        return ratioList;
    }

    /**
     * ADC值转换为重量
     * @param adcVals 十个点压力数据
     * @param datas 校准数据
     * @return
     */
    private static List<Long> computingPressure(List<Float> adcVals, JSONArray datas){
        if (adcVals == null || adcVals.size() != 10  || datas.length() != 10) return null;
        List<Long> pressureList = new ArrayList<>();
        for (int i = 0; i < adcVals.size(); i++) {
            Float aFloat = adcVals.get(i);
            try {
                JSONObject footItem = datas.getJSONObject(i);
                JSONArray pointItems = footItem.getJSONArray("pointItems");
                //            List<Map<String, Object>> list = datas.get(i);
                long pressure = 0;
                for (int j = 0; j < pointItems.length(); j++) {
                    JSONObject pointDataItem = pointItems.getJSONObject(j);
                    double adcMax = pointDataItem.getInt("adcValue");
                    int pMax = pointDataItem.getInt("pressure");
//                    Map<String, Object> maxMap = list.get(j);
//                    double adcMax = Double.parseDouble(maxMap.get("adcValue").toString());
//                    int pMax = Integer.parseInt(maxMap.get("pressure").toString());
                    int compareTo = new BigDecimal(aFloat).compareTo(new BigDecimal(adcMax));
                    if (compareTo == 0 ){
                        pressure = pMax;
                        break;
                    } else if (compareTo < 0) {
                        JSONObject minMap = pointItems.getJSONObject(j-1);
                        double adcMin = minMap.getInt("adcValue");
                        int pMin = minMap.getInt("pressure");
//                        Map<String, Object> minMap = list.get(j-1);
//                        double adcMin = Double.parseDouble(minMap.get("adcValue").toString());
//                        int pMin = Integer.parseInt(minMap.get("pressure").toString());
                        pressure =  count(aFloat,adcMin,pMin,adcMax,pMax);
                        break;
                    }
                }
                pressureList.add(pressure);
            } catch (JSONException e) {
                throw new RuntimeException(e);
            }

        }
        return pressureList;
    }

    /**
     * 计算单个点位的重量
     * @param aDouble 实时ADC值
     * @param adcMin
     * @param pMin
     * @param adcMax
     * @param pMax
     * @return
     */
    private static Integer count(Float aDouble,double adcMin,int pMin,double adcMax,int pMax){
        BigDecimal v1 = new BigDecimal(aDouble).subtract(new BigDecimal(adcMin));
        BigDecimal v2 = new BigDecimal(pMax).subtract(new BigDecimal(pMin));
        BigDecimal v3 = new BigDecimal(adcMax).subtract(new BigDecimal(adcMin));
        BigDecimal add = v1.multiply(v2).divide(v3,2, RoundingMode.HALF_UP).add(new BigDecimal(pMin)).setScale(0, RoundingMode.DOWN);
        return Integer.parseInt(String.valueOf(add));
    }


    /**
     * 获取过滤后10个点的平均值
     * @return
     */
    private static List<Float> getBulEvaluationValue(){
        Queue<BulDataObject> bulDataObjects = DateQueue;
        List<List<Float>> pressurePointData = new ArrayList<>();
        for (BulDataObject i : bulDataObjects) {
            pressurePointData.add(i.getPressurePointData());
        }

        List <Float> floats = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            float sum = 0;
            for (int j = 0; j < pressurePointData.size(); j++) {
                sum = sum + pressurePointData.get(j).get(i);
            }
            BigDecimal divide = new BigDecimal(sum).divide(new BigDecimal(pressurePointData.size()), 2, RoundingMode.HALF_UP);
            floats.add(divide.floatValue());
        }
        return floats;
    }

    /**
     * 获取压力平均值
     * @return
     */
    private static Double getPressureEvaluationValue(){
        Queue<BulDataObject> bulDataObjects = DateQueue;
        float sum = 0;
        for (BulDataObject i : bulDataObjects) {
            sum = sum + i.getPressureData();
        }
        BigDecimal divide = new BigDecimal(sum).divide(new BigDecimal(bulDataObjects.size()), 2, RoundingMode.HALF_UP);
        return divide.doubleValue();
    }


    /**
     * 获取总负重
     * @param type
     * @return
     */
    private static Integer getTotalWeight(int type){
        long l = 0;
        if (type == 1 && rTimestamp != null){
            l = lTimestamp - rTimestamp;
        }else if (type == 2 && lTimestamp != null){
            l = rTimestamp - lTimestamp;
        }

        if (l <= timeInterval){

            totalWeight = lWeight + rWeight;
//            List<String>list = Arrays.asList("totalWeight="+totalWeight,"lTimestamp="+lTimestamp,"rTimestamp="+rTimestamp,"lWeight="+lWeight,"rWeight="+rWeight);
//            Log.i("DataComputingManage", JSONArray.toJSONString(list));
        }
        return totalWeight;
    }

    /**
     * 计算电量
     * @param quantityElectricity
     * @return
     */
    public static int calculateElectricityConsumption(Float quantityElectricity){
        int intValue = BigDecimal.valueOf((quantityElectricity - 3300) / (4200 - 3300) * 100).intValue();
        return Math.min(intValue, 100);
    }


    /**
     * 计算信号强度
     * @param signal
     * @return
     */
    public static int calculateSignalStrength(Float signal){
        float stepNum= (float) (signal.floatValue()/63.75)+0.5f;
        int nValue=(int)(4+stepNum);
        if(nValue<1) nValue=1;
        else if(nValue>4) nValue=4;
        return nValue;
        //int intValue = new BigDecimal(255).subtract(new BigDecimal(signal)).divide(new BigDecimal(63), 2, RoundingMode.CEILING).intValue();
        //return Math.min(intValue, 4);
    }




}
